package com.miyu.client1.utils.redis.redisUtils.config;

import com.miyu.client1.utils.redis.redisUtils.entity.RedisEntity;
import com.miyu.client1.utils.redis.redisUtils.manager.Knife4jRedisManager;
import com.miyu.client1.utils.redis.redisUtils.props.JsonSerialType;
import com.miyu.client1.utils.redis.redisUtils.register.Knife4jRedisRegister;
import com.miyu.client1.utils.redis.redisUtils.util.*;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.util.*;

@AutoConfigureBefore({RedisAutoConfiguration.class})
@Import(Knife4jRedisRegister.class)
@EnableCaching
@Configuration
public class Knife4jRedisConfiguration implements EnvironmentAware, ApplicationContextAware {
    private final static ResourceBundle resourceBundle = ResourceBundle.getBundle("application");

    private static String key1 = "redisTemplate";
    private static String key2 = "stringRedisTemplate";
/*    //服务器地址
    private  final static  String hostName = resourceBundle.getString("spring.redis.host");
    //对应的配置DB
    private  final static  String dbs = resourceBundle.getString("spring.redis.databases");
    //连接端口
    private  final static  int port = Integer.valueOf(resourceBundle.getString("spring.redis.port"));
    //密码
    private  final static  String passWord = resourceBundle.getString("spring.redis.password");
    //连接池最大连接数（使用负值表示没有限制）
    private  final static  int maxActive = Integer.valueOf(resourceBundle.getString("spring.redis.jedis.pool.max-active"));
    //连接池中的最大空闲连接
    private  final static  int maxWait = Integer.valueOf(resourceBundle.getString("spring.redis.jedis.pool.max-wait"));
    //连接池中的最大空闲连接
    private  final static  int maxIdle = Integer.valueOf(resourceBundle.getString("spring.redis.jedis.pool.max-idle"));
    //连接池中的最小空闲连接
    private  final static  int minIdle = Integer.valueOf(resourceBundle.getString("spring.redis.jedis.pool.min-idle"));
    //连接超时时间
    private  final static  int  timeout = Integer.valueOf(resourceBundle.getString("spring.redis.timeout"));
    //是否启用redis*/
    private  final static  String enable = resourceBundle.getString("spring.redis.enable");

    Map<String, RedisTemplate> redisTemplateMap = new HashMap<>();
    Map<String, StringRedisTemplate> stringRedisTemplateMap = new HashMap<>();
    private Binder binder;
    private Environment environment;

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
        this.binder = Binder.get(this.environment);
    }
    @PostConstruct
    public Map<String,RedisTemplate> initRedisTemplate(){
        if(!enable.equals("true"))
            return null;
        RedisEntity redisEntity;
        try {
            redisEntity = binder.bind("spring.redis", RedisEntity.class).get();

        } catch (NoSuchElementException e) {
            throw new RuntimeException("Failed to configure knife4j redis: 'knife4j.redis' attribute is not specified and no embedded redis could be configured.");
        }

        //根据多个库实例化出多个连接池和Template
        List<Integer> databases = redisEntity.getDatabases();
        if(databases == null || databases.size() == 0){
        //    logger.warn("no config property knife4j.redis.databases , default use db0！！！");
            databases.add(0);
        }

        //根据指定的数据库个数来加载对应的RedisTemplate
        for (Integer database : databases) {
            String key = key1 + database;
            RedisTemplate redisTemplate = applicationContext.getBean(key , RedisTemplate.class);
            if(redisTemplate != null){
                redisTemplateMap.put(key , redisTemplate);
            }

            key = key2 + database;
            if(stringRedisTemplateMap != null){
                StringRedisTemplate stringRedisTemplate = applicationContext.getBean(key , StringRedisTemplate.class);
                stringRedisTemplateMap.put(key , stringRedisTemplate);
                System.out.println("初始化db： "+database+"   成功");
            }
        }
        if(redisTemplateMap.size() == 0 && stringRedisTemplateMap.size() == 0){
            throw new RuntimeException("load redisTemplate failure , please check knife4j.redis property config！！！");
        }
        return redisTemplateMap;
    }

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }


    @Bean
    public Knife4jRedisManager knife4jRedisManager(){
        return new Knife4jRedisManager(redisTemplateMap , stringRedisTemplateMap);
    }

    @Bean
    public RedisBaseUtil redisBaseUtil(){
        return new RedisBaseUtil();
    }
    @Bean
    public RedisValUtil redisValUtil(){
        return new RedisValUtil();
    }
    @Bean
    public RedisListUtil redisListUtil(){
        return new RedisListUtil();
    }
    @Bean
    public RedisHashUtil redisHashUtil(){
        return new RedisHashUtil();
    }
    @Bean
    public RedisSetUtil redisSetUtil(){
        return new RedisSetUtil();
    }

}
